package com.ht.controller;

import com.ht.bean.Emp;
import com.ht.bean.Holiday;
import com.ht.service.HolidayService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

@Controller
@RequestMapping("/holiday")
public class HolidayController {

    /*
     *请假表控制层
     * @param
     * @return
     **/

    @Autowired
    private HolidayService holidayService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;//运行时服务接口

    @Autowired
    private TaskService taskService;//任务服务接口

    @Autowired
    private HistoryService historyService;//历史任务服务接口

    //去员工请假页面
    @RequestMapping("/goholiday")
    public String fillin() {
        return "holiday";
    }

    //上传流程文件
    @RequestMapping("/goupload")
    public String goupload() {
        return "upload";
    }

    //去填写请假单
    @RequestMapping("/goapply")
    public String goapply(Model model) {
        List<Emp> empList = holidayService.empList();
        model.addAttribute("empList", empList);
        return "apply";
    }

    //去填写请假单
    @RequestMapping("/gomyTask")
    public String gomyTask(Model model) {
        return "myTask";
    }
    //查询所有请假信息
    @RequestMapping("/holidayMessage")
    /*
     *以JSON格式传输数据
     * @param
     * @return
     **/
    @ResponseBody
    public Map empmessage(Integer page, Integer limit, Holiday holiday, Emp emp) {
        List<Map> list = holidayService.selectHoliday((page - 1) * limit, limit, emp, holiday);
        Map map = new HashMap();
        map.put("code", 0);
        map.put("msg", "成功");
        map.put("count", holidayService.countEmp(emp, holiday));
        map.put("data", list);
        return map;
    }


    //上传流程文件
    @RequestMapping("/upload")
    public String upload(MultipartFile actfile) {
        try {
            //将MultipartFile转换位File
//            File file = new File("c:/test.zip");
//            actfile.transferTo(file);
//
            Deployment deployment = repositoryService.createDeployment().name("部署员工请假流程图").addZipInputStream(new ZipInputStream(actfile.getInputStream())).deploy();
            //Deployment deployment = repositoryService.createDeployment().name("请求流程部署").addClasspathResource("bpmn/empLeave.bpmn20.xml").addClasspathResource("bpmn/empLeave.png").deploy();
            System.out.println("部署ID：" + deployment.getId() + "部署名：" + deployment.getName());
            //file.delete();//删除临时文件
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "redirect:allprod";//去所有流程定义列表
    }

    //查看所有流程定义ProcessDefinition
    @RequestMapping("/allprod")
    public String addprod(Model model) {
        //创建流程定义查询对象
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        processDefinitionQuery.latestVersion();
        //查询所有流程定义
        List<ProcessDefinition> queryList = processDefinitionQuery.list();
        model.addAttribute("quertList", queryList);
        return "allProcessDefinition";
    }

    //删除定义
    @RequestMapping("/delprod")
    public String delprod(String id) {
        repositoryService.deleteDeployment(id, true);
        return "redirect:allprod";//去所有流程图定义列表
    }

    //查看流程图
    @RequestMapping("/viewImage")
    public void viewImage(String id, String imageName, HttpServletResponse resp) {
//读取流程图的流程图片
        InputStream in = repositoryService.getResourceAsStream(id, imageName);
        //把图片打印到网页
        try {
            OutputStream out = resp.getOutputStream();
            // 把图片的输入流程写入resp的输出流中
            byte[] b = new byte[1024];
            for (int len = -1; (len = in.read(b)) != -1; ) {
                out.write(b, 0, len);
            }
            // 关闭流
            out.close();
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    //下载流程图的zip文件
    @RequestMapping("/toExport")
    public void toExport(String id, HttpServletResponse resp) {

        try {
            //设置response对象的头参数，attachment就是附件，filename=文件名称
            resp.setHeader("Content-disposition", "attachment;filename=" + id + ".zip");
            //下载的文件类型是zip文件
            resp.setContentType("application/x-zip-compressed");

            //----------------------------------------------------------------------------


            //通过id拿到流程定义
            ProcessDefinition processDefinition = repositoryService
                    .createProcessDefinitionQuery()
                    .processDefinitionId(id).singleResult();
            //部署id
            String deploymentId = processDefinition.getDeploymentId();

            //bpmn资源文件名称
            String resourceName_bpmn = processDefinition.getResourceName();
            //bpmn资源文件输入流
            InputStream inputStream_bpmn = repositoryService.getResourceAsStream(deploymentId, resourceName_bpmn);
            //png文件名称
            String resourceName_png = processDefinition.getDiagramResourceName();
            //png资源文件输入流
            InputStream inputStream_png = repositoryService.getResourceAsStream(deploymentId, resourceName_png);

            //------创建输出流，绑定到response对象-------------------------------------------------------
            OutputStream out = resp.getOutputStream();
            //创建ZIP输出对象，绑定到输出流
            ZipOutputStream zipo = new ZipOutputStream(out);

            //流复制
            byte[] b = new byte[1024];
            int len = -1;

            //定义zip压缩包中的文件对象（zip实体）
            ZipEntry ze = new ZipEntry(resourceName_bpmn);
            //把创建的实体对象放到压缩包中
            zipo.putNextEntry(ze);
            //文件内容拷贝
            while ((len = inputStream_bpmn.read(b, 0, 1024)) != -1) {
                zipo.write(b, 0, b.length);
            }
            zipo.closeEntry();
            //---------------
            ZipEntry ze1 = new ZipEntry(resourceName_png);
            zipo.putNextEntry(ze1);
            while ((len = inputStream_png.read(b, 0, 1024)) != -1) {
                zipo.write(b, 0, b.length);
            }
            //关闭流
            inputStream_bpmn.close();
            inputStream_png.close();
            zipo.flush();
            zipo.close();
            out.flush();
            out.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @RequestMapping("/addApply")
    public String addApply(Holiday holiday, String empId) {
        holiday.setStatus(1);//设置其他表单数据
        holiday.setHdays(0);
        holiday.setHours(0);
        //调用方法保存单据
        holidayService.addApplay(holiday);
        //设置流程变量
        //设置流程变量，就是将用户的自定义信息带到流程中去绑定
        Map<String, Object> variables = new HashMap<>();
        variables.put("empId", holiday.getEmpId()); //用户名称
        variables.put("holidayDay", holiday.getHolidayDay());//请假天数
        variables.put("holidayId", holiday.getHolidayId());//单据ID
        String assignee = holidayService.selectempName(empId);
        String assignee2 = holidayService.selectempName2();
        System.out.println("部门经理：" + assignee);
        System.out.println("总经理：" + assignee2);

        //设置审批人
        variables.put("assignee1", assignee);
        variables.put("assignee2", assignee2);


        //根据流程key启动流程实例
        ProcessInstance pi = runtimeService.startProcessInstanceByKey(holiday.getProcessInstanceId(), variables);

        // //获取启动流程中当前需要办理的任务 (就是张三的填写申请任务 需要执行完 才能进行到下一个任务节点)
        Task task = taskService.createTaskQuery().processInstanceId(pi.getProcessInstanceId()).orderByProcessInstanceId().desc().singleResult();
        //根据任务ID完成当前任务 (填写也是一个任务 需要完成)
        taskService.complete(task.getId(), variables);
        System.out.println("申请成功...");

        Map map = new HashMap();
        map.put("code", "0");
        map.put("msg", "成功");

        return "redirect:myjob";
    }

    @RequestMapping("/myjob")
    public String myjob(HttpSession session, Model model) {
        String empId = session.getAttribute("empID").toString();
        List<Holiday> holidayList = holidayService.selHoliday(empId);
        model.addAttribute("holidayList", holidayList);
        return "myJobList";
    }

    //查看流程图片
    @RequestMapping("/lookTaskImg")
    public String lookTaskImg(Integer holidayId, Model model, String processInstanceId) {
        try {
            /**
             * 1.在我的任务中传递的参数是instId（实例id）
             * 2.在我的申请单中传递的参数是job.jobId(单据id)
             * */
            //获取流程id
            //String processInstanceId = null;
            if (processInstanceId == null) {
                //通过单据id查找实例对象
                HistoricVariableInstance hvi = historyService.createHistoricVariableInstanceQuery().variableValueEquals("holidayId", holidayId).singleResult();
                processInstanceId = hvi.getProcessInstanceId();//获取流程实例ID
            }
            //  获取历史流程实例
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(processInstanceId).singleResult();

            if (historicProcessInstance == null) {
                throw new Exception();
            } else {
                //获取流程定义信息
                ProcessDefinition pd = repositoryService.getProcessDefinition(historicProcessInstance.getProcessDefinitionId());
                // 获取流程定义的实体（包含了流程中的任务节点信息，连线信息）
                ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) pd;
                // 获取流程历史中已执行节点，并按照节点在流程中执行先后顺序排序
                List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
                        .processInstanceId(processInstanceId).orderByHistoricActivityInstanceId().asc().list();
                // 已经激活的节点ID集合
                //激活的节点（1.任务已经完成；2.任务已经开始，但还未结束）
                List mapList = new ArrayList();
                //获取已经激活的节点ID
                for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {
                    //getActivityId方法获取已经激活的节点id
                    ActivityImpl activityImpl = processDefinition.findActivity(activityInstance.getActivityId());
                    //获取当前节点在图片中的坐标位置，左上角坐标及长宽
                    int x = activityImpl.getX();
                    int y = activityImpl.getY();
                    int height = activityImpl.getHeight();
                    int width = activityImpl.getWidth();
                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put("x", x + 195);
                    map.put("y", y + 76);
                    map.put("height", height);
                    map.put("width", width);
                    mapList.add(map);
                }

                model.addAttribute("mapList", mapList);
                model.addAttribute("pd", pd);//流程定义
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "image";
    }

    //查询我的员工请假审批任务
    @RequestMapping("/myTask")
    public String myTask(HttpSession session, Model model) {
        String empID = session.getAttribute("empID").toString();
        //获取当需要前用户办理的任务列表
        List<Task> taskList = taskService.createTaskQuery().taskAssignee(empID).list();
        model.addAttribute("taskList", taskList);
        System.out.println("我的任务列表" + taskList);
        return "myTask";
    }


    //审批员工请假任务
    @RequestMapping("/taskDetail")
    public String taskDetail(String taskId, String instId, Model model) {
        //流程实例
        ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(instId).singleResult();

        //任务详情
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        //获取历史审批批注信息
        List<Comment> commentList = taskService.getProcessInstanceComments(task.getProcessInstanceId());

        //获取流程定义id
        String processDefineId = task.getProcessDefinitionId();
        //查询流程定义实体对象
        ProcessDefinitionEntity pdentity = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefineId);
        //获取当前活动id
        String activeId = pi.getActivityId();
        //获取当前活动
        ActivityImpl impl = pdentity.findActivity(activeId);


        //获取当前活动结束之后连线的名称
        List<Map> pvmList = new ArrayList<Map>();


        //根据当前节点 获取之后的连线列表
        List<PvmTransition> plist = impl.getOutgoingTransitions();
        for (PvmTransition pvm : plist) {
            Map map = new HashMap();
            if (pvm.getProperty("name") == null) {
                map.put("id", "2");
                map.put("name", "同意");
                map.put("name2", "不同意");
            } else {
                map.put("id", pvm.getId());
                map.put("name", pvm.getProperty("name") + "");
            }
            pvmList.add(map);
            //			pvmList.add(new MapBean(pvm.getId(),pvm.getProperty("name").toString()));
        }

        //反向根据任务ID 得到jobId
        int holidayId = Integer.parseInt(taskService.getVariable(taskId, "holidayId").toString());
        System.out.println("empID=" + taskService.getVariable(taskId, "empID"));

        System.out.println("holidayId=" + holidayId);

        //取出请假单数据
        Holiday holiday = holidayService.findObjById(holidayId);


        model.addAttribute("commentList", commentList);
        model.addAttribute("pvmList", pvmList);
        System.out.println("审批选项选项：" + pvmList);
        model.addAttribute("holiday", holiday);
        model.addAttribute("taskId", taskId);
        System.out.println("taskId = " + taskId);
        return "adult";
    }

    //审批任务
    @RequestMapping("/complete")
    public String complete(String taskId, Integer holidayId, HttpSession session, String comment, String flow) {
        //获取当前Task对象
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        System.out.println("--------------------------------------\ntask=：" + task);
        System.out.println("taskId = " + taskId);
        //获取当前实例对象Id
        String processId = task.getProcessInstanceId();
        //获取jobId变量
        //取出请假单数据
        Holiday holiday = holidayService.findObjById(holidayId);
        //获取当前登录的用户id
        String empId = session.getAttribute("empID").toString();
        //添加备注的处理人
        Authentication.setAuthenticatedUserId(empId);
        //添加审批意见
        taskService.addComment(taskId, processId, comment);
        //添加任务变量
        Map<String, Object> var = new HashMap<String, Object>();
        var.put("flow", flow);
//    	var.put("assignee", userid);
        //完成当前任务
        taskService.complete(taskId, var);


        //判断当前流程是否已经审批结束
        ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();

        //如果pi==null表示流程审批结束
        if (pi == null) {
            if (flow.equals("不同意")) {
                //更新job表的状态为2
                holiday.setStatus(3);
            } else {
                holiday.setStatus(2);
            }
            holidayService.updHoliday(holiday);
        }
        return "redirect:myTask";
    }

    @RequestMapping("/lookComment")
    public String lookComment(Integer holidayId, Model model) {
        //通过单据id查找实例对象
        HistoricVariableInstance hvi = historyService.createHistoricVariableInstanceQuery().variableValueEquals("holidayId", holidayId).singleResult();
        //获取流程实例id
        String piId = hvi.getProcessInstanceId();
        //通过实例id查找批注信息列表
        List<Comment> commentList = taskService.getProcessInstanceComments(piId);
        model.addAttribute("commentList", commentList);
        return "comment";
    }

    @RequestMapping("/deleteHolidayId")
    @ResponseBody
    public Map deleteHolidayId(Integer holidayId){
        Map map = new HashMap();
        boolean bln =  holidayService.deleteHolidayId(holidayId);
        if (bln){
            map.put("msg","删除成功！");
        } else {
            map.put("msg","删除失败！");
        }
        return map;
    }

    /*
     *查看某个员工的请假条信息
     * @param
     * @return
     **/
    @RequestMapping("/goLookHolidayContent/{holidayId}")
    private String goLookWeeklyContent(Model model,@PathVariable Integer holidayId){
        List<Map> list = holidayService.LookHolidayContent(holidayId);
        model.addAttribute("LookHolidayContent",list);
        System.out.println(list);
        return "LookHolidayContent";
    }

}
